#include "mg_Rs485Config.h"
#include "mg_Rs485Protocol.h"
#include "mg_Device.h"

//static sem_t UartSem;//定义串口接收信号量

//=============================< 发送退避定时器 >====================================
//使能发送时钟(us)
void RS485SendTimEnable(uint16_t tm)
{
	RS485TxData.BackTimeCnt = tm;
	RS485TxData.BackTimerEnble = true;
}
//停止发送时钟
void RS485SendTimDisable(void)
{
	RS485TxData.BackTimerEnble = false;
}
//=============================< 总线空闲检测脚 >================================
//引脚初始化
static void RS485ExtiGpioInit(void)
{
	ithGpioSetMode(RS485_INT_PIN, ITH_GPIO_MODE0); //设定GPIO模式0
	ithGpioSetIn(RS485_INT_PIN); //设定为输入
	ithGpioCtrlEnable(RS485_INT_PIN, ITH_GPIO_PULL_ENABLE); //设定内部拉功能启用
	//ithGpioCtrlEnable(RS485_INT_PIN, ITH_GPIO_PULL_UP); //设定内部上拉
	ithGpioEnable(RS485_INT_PIN); //使能此IO
}
//中断初始化
static void RS485ExtiInit(void)
{
	ithEnterCritical(); //
	ithGpioClearIntr(RS485_INT_PIN); //清除先前的中斷事件
	ithGpioRegisterIntrHandler(RS485_INT_PIN, RS485ExtiIsr, (void*)RS485_INT_PIN); //註冊此 GPIO pin 的 ISR
	ithGpioCtrlEnable(RS485_INT_PIN, ITH_GPIO_INTR_LEVELTRIGGER);//设定中断为边缘触发
	ithGpioCtrlEnable(RS485_INT_PIN, ITH_GPIO_INTR_BOTHEDGE);//设定中断为单边沿触发
	ithGpioCtrlEnable(RS485_INT_PIN, ITH_GPIO_INTR_TRIGGERFALLING);//设定中断为上升沿触发
	ithIntrEnableIrq(RS485_INT_PIN); //啟動 GPIO 的中斷功能(中斷控制器)
	ithGpioEnableIntr(RS485_INT_PIN); //啟動此 GPIO pin 的中斷功能
	ithExitCritical(); //unlock spinlock(建議使用)
}
//=============================< 发送使能脚 >====================================

//=============================< 串口配置 >====================================

//重定义的回调函数
static void RS485Callback(void* arg1, uint32_t arg2)
{
	uint8_t dat[256] = { 0 };
	int len = 0;
	len = read(RS485_PORT, dat, 256);
	//printf("Uart Recieve:%s\n", dat);
	RS485TxData.Busy = true;
	//if (SendDataNow == true)return;
	//使能接收完成计数器
	RS485RxData.TimeCnt = 0;
	RS485RxData.TimeEnble = true;
	//保存字节
	if (RS485RxData.ptrBufWrite + len >= USART_RXDATA_LEN)
	{
		RS485RxData.RxLock = true;
		return;
	}
	memcpy(&RS485RxData.Buf[RS485RxData.ptrBufWrite], dat, len);
	RS485RxData.ptrBufWrite += len;
	//don`t add any codes here.
	//sem_post(&UartSem);
}
//串口配置
void RS485UsartInit(void)
{
#ifdef _WIN32
#else
	printf("\nMoorgen INFO : Rs485 Init start......");
	itpRegisterDevice(RS485_PORT, &RS485_DEVICE);
	ioctl(RS485_PORT, ITP_IOCTL_RESET, RS485_BAUDRATE);
	ioctl(RS485_PORT, ITP_IOCTL_REG_RS485_DEFER_CB, (void*)RS485Callback);
	printf("\nMoorgen INFO : Rs485 Init success!");
#endif
}
//485串口发送
void Uart1_Send(uint8_t* SendData, uint8_t DataLen)
{
	uint8_t i;
	write(RS485_PORT, SendData, DataLen);
	//Dubug
	printf("Moorgen INFO : Rs485 Send: ");
	for (i = 0; i < DataLen; i++)
	{
		printf("%02X ", SendData[i]);
	}
	printf("\n");
}
//485串口接收
int Uart1_Recieve(char* RecieveData)
{
	return read(RS485_PORT, RecieveData, 1);
}
void Clean_Rs485_Data(void)
{
	char Byte;
	uint8_t i;
	while (Uart1_Recieve(&Byte));
	printf("Moorgen INFO : Clean 485 Data over.\n");
}
//===================================< 串口初始化 >=========================================
//RS485初始化
void RS485Init(void)
{
	//USART1
	RS485ExtiGpioInit();//总线空闲检测脚
	RS485ExtiInit();//中断初始化
	UsartValuInit();//串口发送标志初始化
	RS485UsartInit();//串口信号量及配置初始化
}
